superstrict

framework BRL.Blitz
import BRL.StandardIO
import BRL.PolledInput
import BRL.Random
import Bah.RakNet

seedRnd(milliSecs());

(new ClientTest).main();

type ClientPeer

	function create:ClientPeer(threadSleepTimer:short, serverIP:string, serverPort:short, localPort:short, tries:short)
	
		local c:ClientPeer= new ClientPeer;
		
		c.m_peer = TRKRakNetworkFactory.GetRakPeerInterface();
		c.m_socketDescr = TRKSocketDescriptor.CreateSocketDescriptor(localPort);
		c.m_sysaddr = c.m_peer.GetInternalID(UNASSIGNED_SYSTEM_ADDRESS);
		c.m_con_ipaddr = serverIP;
		c.m_con_port = serverPort;
		c.m_con_tries = tries;
		c.m_serveraddr = null;
		
		c.m_peer.Startup(1, threadSleepTimer, c.m_socketDescr);
		
		return c;
	
	end function
	
	method connect:byte()
	
		if (not m_peer.connect(m_con_ipaddr, m_con_port, "", m_con_tries)) ..
			return false;
		
		local packet:TRKPacket = null;
		local data:string = null;
		local msgType:short = 0;
		local senderAddr:TRKSystemAddress = null;
		
		while (true)
		
			packet = m_peer.Receive();
			
			if (packet)
			
				data = string.FromCString(packet.GetData());
				msgType = packet.GetPacketIdentifier();
				senderAddr = packet.GetSystemAddress();
				
				select (msgType)
				
					case ID_CONNECTION_BANNED
						return 3;
					case ID_CONNECTION_REQUEST_ACCEPTED
						m_serveraddr = senderAddr;
						return 1;
					case ID_CONNECTION_ATTEMPT_FAILED
						return 0;
					case ID_ALREADY_CONNECTED
						return 2;
				
				end select
			
			end if
		
		end while
	
	end method
	
	method isConnected:byte()
	
		return not (m_serveraddr = null or not m_peer.IsConnected(m_serveraddr));
	
	end method
	
	method managePackets()
	
		local packet:TRKPacket = m_peer.Receive();
		
		if (packet)
		
			local data:string = string.FromCString(packet.GetData());
			local msgType:int = packet.GetPacketIdentifier();
			local senderAddr:TRKSystemAddress = packet.GetSystemAddress();
			local senderPort:string = senderAddr.GetPort();
			local senderIndex:int = m_peer.GetIndexFromSystemAddress(senderAddr);
			
			select (msgType)
			
				case ID_CONNECTION_BANNED
					print("You are banned from this server.");
				case ID_MODIFIED_PACKET
					print("WARNING: Received modified packet from " + senderAddr.ToString() + ":" + senderPort + "!")
				case ID_DISCONNECTION_NOTIFICATION
					print("Disconnected from the server.");
				default
					print("Unknown packet received from " + senderAddr.ToString() + ":" + senderPort + ..
						" containing the data ~q" + data + "~q.");
			
			end select
		
		end if
	
	end method
	
	method destroy()
	
		m_peer.Shutdown(300);
		TRKRakNetworkFactory.DestroyRakPeerInterface(m_peer);
	
	end method
	
	field m_peer:TRKRakPeerInterface;
	field m_socketDescr:TRKSocketDescriptor;
	field m_sysaddr:TRKSystemAddress;
	field m_con_ipaddr:string;
	field m_con_port:short;
	field m_con_tries:short;
	field m_serveraddr:TRKSystemAddress;

end type

type ClientTest

	method main()
	
		local client_peer:ClientPeer = ClientPeer.create(30, "85.227.135.251", 27530, getRandomPort(), 2);
		local connectionResult:byte = 0;
		
		print("Connecting to: " + client_peer.m_con_ipaddr + ":" + client_peer.m_con_port + "...");
		
		connectionResult = client_peer.connect();
		
		select (connectionResult)
		
			case 0
				print("Connection failed.");
				delay(1000);
				client_peer.destroy();
				end;
			case 1
				print("Connection established.");
			case 2
				print("Already connected.");
			case 3
				print("You are banned from this server.");
				delay(1000);
				client_peer.destroy();
				end;
		
		end select
		
		while (true)
		
			delay(10);
			client_peer.managePackets();
		
		end while
		
		client_peer.destroy();
	
	end method
	
	method getRandomPort:short()
	
		return rand(22000, 27400);
	
	end method

end type
